
const isObject = value => value !== null && typeof value === 'object'
const convert = value => isObject(value) ? reactive(value) : value
const hasOwnProperty = Object.prototype.hasOwnProperty
const hasOwn = (target, key) => hasOwnProperty.call(target, key)
export function reactive (target) {
    if(!isObject(target)) return
    const handler = {
        get(target, key, receiver){
            //收集依赖
            track(target, key)
            const result = Reflect.get(target, key, receiver)
            return convert(result)
        },
        set(target, key, value, receiver){
            const oldVal = Reflect.get(target, key, receiver)
            const result = true
            if(oldVal !== value){
                result = Reflect.set(target, key, value, receiver)
                //触发更新
                trigger(target, key)
            }
            return result
        },
        deleteProperty(target, key){
            const hadkey = hasOwn(target, key)
            const result = Reflect.deleteProperty(target, key)
            if(hadkey && result){
                //触发更新
                trigger(targert, key)
            }
            return result
        }
    }
    return new Proxy(target, handler)
}

let activeEffect = null
export  function effect (callback){
    activeEffect = callback
    callback()
    activeEffect = null
}

let targetMap = new WeakMap() 
export function track (target, key){
    if(!activeEffect) return
    let depsMap = targetMap.get(target)
    if(!depsMap){
        targetMap.set(target, (depsMap = new Map))
    }
    let dep = depsMap.get(key)
    if(!dep){
        depsMap.set(key, (dep = new Set()))
    }
    dep.add(activeEffect)
}

export function trigger (target, key) {
    const depsMap = targetMap.get(target)
    if(!depsMap) return
    const dep = depsMap.get(key)
    if(dep){
        dep.forEach(effect => {
            effect()
        });
    }
}

export function ref (raw) {
    if(isObject(raw) && raw.__V_isRef) return
    let value = convert(row)
    const f = {
        __V_isRef: true,
        get value(){
            track(r, 'value')
            return value
        },
        set value(newValue){
            if(!newValue === value){
                raw = newValue //不明白为什么需要这行代码
                value  = convert(raw)
                trigger(r, 'value')
            }
        }
    }
    return r
}

export function toRefs (proxy){
    //省略了判断是否为toRefs转换的对象
    const ret = proxy instanceof Array ? new Array(proxy.length) : {}
    for (const key in proxy){
        ret[key] = toProxyRef(proxy, key)
    }
    return ret
}

function toProxyRef (proxy, key){
    const r = {
        __V_isRef: true,
        get value(){
            return proxy[key]
        },
        set value(newValue){
            proxy[key] = newValue
        }
    }
    return r
}

export function computed (getter){
    const result = ref()
    effect(() => result.value = getter())
    return result
}